package src

import (
	"log"
	"math/rand"
	"strconv"
	"sync"
	"time"
)

// 多个生产者，多个消费者 (S s R s)
// 引入一个协调者来关闭附加的退出信号 channel

func SsRsChannel() {
	rr := rand.New(rand.NewSource(time.Now().UnixNano()))
	log.SetFlags(0)

	wgReceivers := sync.WaitGroup{}
	wgReceivers.Add(NumReceivers)

	dataCh := make(chan int, 100)
	stopCh := make(chan struct{})

	toStop := make(chan string, 1)

	var stoppedBy string

	// moderator
	go func() {
		stoppedBy = <-toStop
		close(stopCh)
	}()

	// senders
	for i := 0; i < NumSenders; i++ {
		go func(id string) {
			for {
				val := rr.Intn(MaxRandomNumber)
				if val == 0 {
					select {
					case toStop <- "sender#" + id:
					default:
					}
					return
				}

				select {
				case <-stopCh:
					return
				case dataCh <- val:
				}
			}
		}(strconv.Itoa(i))
	}

	// receivers
	for i := 0; i < NumReceivers; i++ {
		go func(id string) {
			defer wgReceivers.Done()

			for {
				select {
				case <-stopCh:
					return
				default:
				}

				select {
				case <-stopCh:
					return
				case val := <-dataCh:
					if val == MaxRandomNumber-1 {
						select {
						case toStop <- "receiver#" + id:
							log.Println(val)
						default:
						}
					}
				}
			}

		}(strconv.Itoa(i))
	}

	wgReceivers.Wait()
	log.Println("stopped by", stoppedBy)
}
